---
sidebar_position: 1
title: 基本使用
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

## 前言
以前我们引入 JS 资源总是通过`<script>`标签引用。

<Tabs>
<TabItem value="index.html" label="index.html">

```html
<button>计算1+2</button>
<script src="./src/utils.js"></script>
<script src="./src/index.js"></script>
```

</TabItem>
<TabItem value="index.js" label="index.js">

```js
const btn = document.querySelector("button");
btn.onclick = async () => {
  const res = add(1, 2);
  console.log(res);
};
```

</TabItem>
<TabItem value="utils.js" label="utils.js">

```js
const add = (x, y) => {
  return x + y;
};
```

</TabItem>
</Tabs>

但是这种落后方式引入会有诸多弊端，如：

1. 全局污染
2. 先后执行顺序  
   ...

所以在新版的 JS 中提出了模块化方案，而 chrome 也开始了支持。

<Tabs>
<TabItem value="index.html" label="index.html">

```html
<button>计算1+2</button>
<script type="module" src="./src/index.js"></script>
```

</TabItem>
<TabItem value="index.js" label="index.js">

```js
import { add } from "./utils.js";

const btn = document.querySelector("button");
btn.onclick = async () => {
  const res = add(1, 2);
  console.log(res);
};
```

</TabItem>
<TabItem value="utils.js" label="utils.js">

```js
export const add = (x, y) => {
  return x + y;
};
```

</TabItem>
</Tabs>

不过在早些时候浏览器确是基本都不支持模块，也就是说上边代码会报错"import、export 无法被正确识别解析"。

于是 webpack 就出现了，为了就是能让我们尽早使用上优秀的模块化技术，不用考虑兼容问题。经过 webpack 处理后的代码，引入到浏览器，就可以兼容旧浏览器。

```mermaid
graph LR;
    utils.js-.->|import 引入|index.js;
    index.js-->|Webpack处理|生成Output.js;
    生成Output.js-->|script标签引入|index.html;
```

## 使用
### 安装
同babel一样 将命令行工具、编译核心模块分化为两个包，`webpack`是核心库，`webpack-cli`是终端（命令行）使用的工具。   
webpack分为核心包和终端工具包，这两个包是webpack的基石。
```shell
yarn add --dev webpack webpack-cli
```


### 简单使用
创建一个项目，如下
```
  demo
  |- index.html
  |- /src
    |- index.js
    |- utils.js
```

<Tabs>
<TabItem value="index.html" label="index.html">

```html
<button>计算1+2</button>
<script src="./dist/main.js"></script>
```

</TabItem>
<TabItem value="index.js" label="index.js">

```js
import {add} from "./utils.js";

const btn = document.querySelector("button");
btn.onclick = async () => {
  const res = add(1, 2);
  console.log(res);
};
```

</TabItem>
<TabItem value="utils.js" label="utils.js">

```js
export const add = (x, y) => {
  return x + y;
};
```

</TabItem>
</Tabs>

最后执行命令如下
```shell
npx webpack ./src/index.js --mode=development
```
就会在根目录下生成./dist/main.js。 这个文件 就是webpack做的处理了模块后的代码，引入html即可！

如果你检查 dist/bundle.js，你可以看到 webpack 具体如何实现，这是独创精巧的设计！除了esm，webpack 还能够很好地支持多种其他模块语法。
:::warning
注意，webpack 不会更改代码中除 import 和 export 语句以外的部分。如果你在使用其它 ES2015 特性，请确保你在 webpack 的 loader 系统中使用了一个像是 Babel 或 Bublé 的转译器。
:::

### 配置文件
webpack虽然可以无须任何配置使用，然而大多数项目会需要很复杂的设置，这就是为什么 webpack 仍然要支持 配置文件。这比在终端中手动输入大量命令要高效的多！

根目录下创建一个webpack配置文件
```js title="webpack.config.js"
const path = require('path');

module.exports = {
  mode: "development",
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  }
};
```
然后我们在上边的执行命令改为如下即可，
```shell
npx webpack
```
以上代码等价于 `npx webpack --config webpack.config.js`，因为默认不指定配置文件则会自动查找根目录下的`webpack.config.js`。

比起 CLI 这种简单直接的使用方式，配置文件具有更多的灵活性。我们可以通过配置方式指定 loader 规则(loader rules)、插件(plugins)、解析选项(resolve options)，以及许多其他增强功能。




### 开发工具（dev模式）
每次编译代码都需要手动运行 `build` 会显得很麻烦，一般只有最后的生产产出才会用。   
webpack 提供了3种可选方式（开发工具）帮助在代码发生变化后自动编译代码，其中在多数场景中都会使用 [webpack-dev-server](https://github.com/webpack/webpack-dev-server)，所以我们就暂时只介绍这一个常用的吧。 

webpack-dev-server 提供了一个能够实时重新加载的基本的 web server。 安装好它后，只需要略做配置即可使用！
```js  title="webpack.config.js"
module.exports = {
   // ...
  devServer: {
    static: './dist',
  },
 };
```

最后执行启动服务命令即可`npx webpack serve`

### 优化使用 
我们无论还是打包，都需要使用命令来调用webpack。  
这样还是比较费劲的，我们可以进一步优化。

```js title="package.json"
{
  // ...
  "scripts": {
    "dev": "webpack serve",
    "build": "webpack"
  }
}
```
这样，结合ide，我们就可以鼠标点点就启动了。